package com.example.deepseekwebsocket.service.impl;

import com.example.deepseekwebsocket.service.DeepSeekService;
import com.example.deepseekwebsocket.vo.request.DeepSeekRequest;
import com.example.deepseekwebsocket.vo.response.DeepSeekChatResponse;
import com.example.deepseekwebsocket.vo.response.DeepSeekResponse;
import com.google.gson.Gson;
import okhttp3.*;
import org.jetbrains.annotations.NotNull;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

import java.io.IOException;
import java.util.ArrayList;
import java.util.List;

/**
 * @Author: 菜鸟Lm
 * @Version：1.0
 */
@Service
public class DeepSeekServiceImpl implements DeepSeekService {

    @Value("${deepSeek.chat.url}")
    private String deepSeekChatUrl;

    @Value("${deepSeek.key}")
    private String deepSeekKey;

    // 创建OkHttpClient实例，并设置超时时间
    OkHttpClient client = new OkHttpClient.Builder()
            .connectTimeout(300, java.util.concurrent.TimeUnit.SECONDS)
            .readTimeout(300, java.util.concurrent.TimeUnit.SECONDS)
            .writeTimeout(300, java.util.concurrent.TimeUnit.SECONDS)
            .build();

    @Override
    public String localDeepSeekAip(String message, String systemMessage) throws IOException {
        /**
         * DeepSeeK本地调用地址
         * 1.怎么自动端口号 使用 ollama serve 命令可以看到控制台打印默认端口号：11434
         * 2.怎么自动调用的地址 打开俩个终端分别执行： ollama run deepseek-r1:7b (运行deepseek-r1:7b模型) ；ollama stop (停止ollma)。在运行了
         * 运行deepseek-r1:7b模型终端随便提问题后会报错: 调用http://127.0.0.1:11434/api/chat失败等信息
         *
         */
        //TODO 建议使用配置文件形式
        String url = "http://127.0.0.1:11434/api/chat";

        /**
         * 创建DeepSeekRequest对象 属性注解均在实体类中
         * 官方案例文档地址：https://api-docs.deepseek.com/zh-cn/api/create-chat-completion
         * 注意需要本地有下周对应的模型和ollama处于运行状态
         */
        DeepSeekRequest requestObject = getDeepSeekRequest(message, systemMessage, "deepseek-r1:7b");

        // 使用Gson将请求对象转换为JSON字符串
        Gson gson = new Gson();
        String jsonBody = gson.toJson(requestObject);

        // 设置请求体的媒体类型为JSON
        MediaType mediaType = MediaType.parse("application/json");
        // 创建请求体，包含JSON字符串
        RequestBody body = RequestBody.create(mediaType, jsonBody);
        // 创建HTTP POST请求
        Request request = new Request.Builder()
                .url(url)
                .method("POST", body)
                .addHeader("Content-Type", "application/json")
                .addHeader("Accept", "application/json")
                .build();
        // 发送请求并获取响应
        Response response = client.newCall(request).execute();
        if (!response.isSuccessful()) {
            throw new IOException("Unexpected code " + response);
        }
        // 将响应体内容转换为DeepSeekResponse对象
        DeepSeekResponse deepSeekResponse = gson.fromJson(response.body().string(), DeepSeekResponse.class);
        if (deepSeekResponse.getMessage() == null) {
            return "很抱歉，我暂时无法理解您的问题。";
        }
        return deepSeekResponse.getMessage().getContent();
    }

    @Override
    public String officialDeepSeekAip(String message, String systemMessage) throws IOException {
        /**
         * 创建DeepSeekRequest对象 属性注解均在实体类中
         * 官方案例文档地址：https://api-docs.deepseek.com/zh-cn/api/create-chat-completion
         */
        DeepSeekRequest requestObject = getDeepSeekRequest(message, systemMessage,"deepseek-chat");

        // 使用Gson将请求对象转换为JSON字符串
        Gson gson = new Gson();
        String jsonBody = gson.toJson(requestObject);

        // 设置请求体的媒体类型为JSON
        MediaType mediaType = MediaType.parse("application/json");
        // 创建请求体，包含JSON字符串
        RequestBody body = RequestBody.create(mediaType, jsonBody);
        // 创建HTTP POST请求
        Request request = new Request.Builder()
                .url(deepSeekChatUrl)
                .method("POST", body)
                .addHeader("Content-Type", "application/json")
                .addHeader("Accept", "application/json")
                .addHeader("Authorization", "Bearer " + deepSeekKey)
                .build();

        // 发送请求并获取响应
        Response response = client.newCall(request).execute();
        try {
            if (!response.isSuccessful()) {
                throw new IOException("Unexpected code " + response + " with body " + response.body().string());
            }
            // 读取响应体内容
            String responseBodyString = response.body().string();
            // 将响应体内容转换为DeepSeekResponse对象
            DeepSeekChatResponse deepSeekChatResponse = gson.fromJson(responseBodyString, DeepSeekChatResponse.class);

            // 检查响应内容是否为空
            if (deepSeekChatResponse == null || deepSeekChatResponse.getChoices() == null || deepSeekChatResponse.getChoices().isEmpty()) {
                throw new IOException("Response is empty or does not contain expected data");
            }

            return deepSeekChatResponse.getChoices().get(0).getMessage().getContent();
        } finally {
            response.close();
        }
    }


    @NotNull
    private static DeepSeekRequest getDeepSeekRequest(String message, String systemMessage,String model) {
        DeepSeekRequest requestObject = new DeepSeekRequest();
        List<DeepSeekRequest.Message> messages = new ArrayList<>();
        //用户消息
        messages.add(new DeepSeekRequest.Message(message, "user"));
        //上一条deepseek消息
        messages.add(new DeepSeekRequest.Message(systemMessage, "system"));
        requestObject.setMessages(messages);
        // 模型 根据自身情况调整
        requestObject.setModel(model);
        requestObject.setFrequency_penalty(0);
        requestObject.setMax_tokens(2048);
        requestObject.setPresence_penalty(0);
        requestObject.setResponse_format(new DeepSeekRequest.ResponseFormat("text"));
        requestObject.setStop(null);
        requestObject.setStream(false);
        requestObject.setStream_options(null);
        requestObject.setTemperature(1);
        requestObject.setTop_p(1);
        requestObject.setTools(null);
        requestObject.setTool_choice("none");
        requestObject.setLogprobs(false);
        requestObject.setTop_logprobs(null);
        return requestObject;
    }


}
